
#include <SPI.h>
#include <Ethernet.h>
#include <Servo.h>
#include "smartled.h"

#define DEBUG 1
#define TRACE 0

struct heatduinoStateStruct{
  int homeAway;
  int nightSavingMode;
  int temperature;
  int mode; // Mode: Auto - 1 / Manual - 0 
} 
state;

////////////////////// INTENET SETTINGS ///////////////////////
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,0, 178); //Local lan address
#define IP_PORT 91 //port for our server

// Initialize the Ethernet server library
EthernetServer server(IP_PORT);
#define SERVER_ADDRESS "apt1114.homeip.net:91"

///////////////// MECHANICS /////////////////////

/////////////////////////////////////////////////

// --- GENERAL SETTINGS

#define MIN_BOILER_TEMP 50
#define MAX_BOILER_TEMP 150


//----------Servo----------------
Servo controlServo;  
int pos = 0;    // variable to store the servo position 
#define SERVO_PIN 9
#define MAX_SERVO_POS 160
#define MIN_SERVO_POS 30
int hot_pos = 120; // Position for max hot 150F
int vac_pos = 10;  // min temp 50F


// ---------- MODE SWITCH ---------
#define MODE_SWITCH_PIN 7


// ---------- POTENTIOMENTER ---------
#define POTENT_PIN A0
int outputValue;
int sensorValue;


//------------- RSET BUTTON--------
const int buttonPin = MODE_SWITCH_PIN;     // the number of the pushbutton pin
int buttonState = 0;         // variable for reading the pushbutton status


//------------- OPERATION MODES ----------------
#define AUTO 1
#define MANUAL 0
int mode = MANUAL;
int modeChange;

//------------------LED-------------------------
#define LED_PIN 8
SMARTLED greenLED;


//////////////////////////////////////////////////////////////////
///
///            INTERNET FUNCTIONS
///
/////////////////////////////////////////////////////////////////


#define MAX_BUFF 200
#define COM_ERROR 0
#define SEND_STATE 1
#define UPDATE_PARM 2
#define LOAD_PAGE 3

EthernetClient client;

int sendXMLResponce(int reqType){
  

  //Browser reload button pressed
  if  (reqType==LOAD_PAGE){
    if (DEBUG) Serial.println("Request : LOAD_PAGE - Reload HTML to the browser");
    /*
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println("Connnection: close");
    client.println();
    client.println("<!DOCTYPE HTML>");
    client.println("<html>");
    // some real data here.
    client.println("<h1>PRIVET DAVID</h1>");
    client.println("</html>");
    */
    client.println("HTTP/1.1 301 Moved Permanently");
    char redirectString[120];
    strcpy(redirectString,"Location: http://heatduino.googlecode.com/svn/trunk/HeatduinoWebClient/heatduino.html?address=");
    strcat(redirectString,SERVER_ADDRESS);
    Serial.println(redirectString);
    client.println(redirectString);

    //client.println("Location: http://heatduino.googlecode.com/svn/trunk/HeatduinoWebClient/heatduino.html"+"?address="+SERVER_ADDRESS);
  }


  // responce to http://address/state.xml
  // sending XML with current state
  if  (reqType==SEND_STATE || reqType==UPDATE_PARM){

    if (DEBUG) Serial.println("Responding with current state");
    client.println("HTTP/1.1 200 OK");
    client.println("Access-Control-Allow-Methods: GET, POST, OPTIONS");
    client.println("Access-Control-Allow-Credentials: true");
    client.println("Access-Control-Allow-Origin: *");
    client.println("Access-Control-Allow-Headers: Content-Type, *");
    client.println();

    client.println("<?xml version=\"1.0\"?> ");

    // Current temperature
    client.println("<heatduinodata>");

    client.print("<TEMPSetting>");
    client.print( state.temperature);
    client.println("</TEMPSetting>");

    // Current Home/Away state
    client.print("<HAState>");
    client.print(state.homeAway);
    client.println("</HAState>");

    // Current Night Saving Mode state
    client.print("<NSMState>");
    client.print(state.nightSavingMode);
    client.println("</NSMState>");

    // Current internal clock - HartBit
    client.print("<HARTBit>");
    client.print(millis());
    client.println("</HARTBit>");
    
    // Current internal clock - Mode
    client.print("<Mode>");
    client.print(state.mode);
    client.println("</Mode>");

    client.println("</heatduinodata>");

  }
}

int ProcessXMLRequest(char *buffer){
  int reqType;

  // Request Current State
  if(strstr(buffer, "GET ") && strstr(buffer, "state.xml ")){
    if (TRACE) Serial.println("Client requested Current State XML");
    reqType = SEND_STATE;
  }

  // Request Reload
  if(strstr(buffer, "GET ") && strstr(buffer, "/ ")){
    if (TRACE) Serial.println("Client requested RELOAD");
    reqType = LOAD_PAGE;
  }

  //Request Update a State Parameter
  if(strstr(buffer, "GET ") && strstr(buffer, "state.xml?")){
    if (TRACE) Serial.println("Client requested a state change");
    char key[20];
    char *p;
    char value[20];

    p=strstr( buffer, "state.xml?");
    p=p+strlen("state.xml?");
    p=strtok(p,"=");

    if (!strcmp(p,"HAState")){
      p=strtok(NULL,"=");
      if (atoi(p)==0) state.homeAway=0;
      else state.homeAway=1;
    }
    if (!strcmp(p,"NSMState")){
      p=strtok(NULL,"=");
      if (atoi(p)==0) state.nightSavingMode=0;
      else state.nightSavingMode=1;
    }
    if (!strcmp(p,"TEMPSetting")){
      p=strtok(NULL,"=");
      state.temperature=atoi(p);
    }

    reqType = UPDATE_PARM;
  }

  return (reqType);
}


int getWebRequest(){

  char buffer[MAX_BUFF];
  int buffLen = 0;
  int reqType;
  int firstLineFlag  = true;

  //clean buffer for client request
  memset(buffer,0,MAX_BUFF);

  // listen for incoming clients
  client = server.available();
  if (!client) {
    
    client.stop();
    //delay(50);
    return (0); //No client, will try later
  }


    if (DEBUG) Serial.println("Received a new client request...");

    while (client.connected()) {

      if (client.available()) {
        char c = client.read();
        if (TRACE) Serial.write(c);
        if (c == '\r') 
          continue; // ignore all \r
        if (c != '\n'){
          buffer[buffLen++] = c;
          if (buffLen > MAX_BUFF){
            Serial.println("Unexpected buffer overflow. Exiting.");
            break;
          }
          continue;
        }

        if ((c == '\n') ){ // end of line
          // check for the end of HTTP request (http request ends with a blank line)
          if (buffLen != 0){

            if(firstLineFlag) reqType = ProcessXMLRequest(buffer); //we only care about the first line of the http request
            firstLineFlag = false;

            // clean up buffer and reset count
            memset(buffer,0,MAX_BUFF);
            buffLen=0;
            continue; // next character
          }

          // end of HTTP request
          // send responce and close connection.
          if (buffLen==0){ 
            if (TRACE) Serial.println("End of client request. Sending responce...");
            sendXMLResponce(reqType);
            if (TRACE) Serial.println("Responce sent.");
            break;//end http exchanege
          }
        }
      }
    }

    // give the web browser time to receive the data
    //delay(50);
    // close connection:
   client.stop();
    if (DEBUG) Serial.println("client stopped");
 
  return (reqType);
}



void setup() {

  // Open serial communications and wait for port to open:
  Serial.begin(9600);

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  //delay(100);
  server.begin();
  //delay(100);
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());

  // Set default values in case of reset. 
  // Later the data should be saved on a Flash Card

  state.homeAway = 1; // Home
  state.temperature = 110; //Normal temperature

  state.nightSavingMode = 1; //Night Saving Mode is ON

  modeChange = true;
  controlServo.attach(SERVO_PIN,400,2800);  // attaches the servo on pin 9 to the servo object 
  controlServo.write(90);

  //delay(100);
  pinMode(MODE_SWITCH_PIN, INPUT);  // mode swtch 
  greenLED.ledAttach(LED_PIN); // LED pin

}

// ---- begin from here ----

void loop() {
  static int rc;

  // determine current mode 
  buttonState = digitalRead(buttonPin);
  modeChange = false;
  if ((buttonState == LOW) && (mode != MANUAL)){
    if (DEBUG)  Serial.println("Manual mode");
    mode = MANUAL;  
    modeChange = true;  
  }
  if ((buttonState == HIGH) && (mode != AUTO)){
    if (DEBUG)  Serial.println("Auto mode");
    mode = AUTO;
    modeChange = true;
     }
  
  // get request from browser



  // Let's do whatever  we need to do based on current mode
  switch (mode){

  case MANUAL:
    
    state.mode=MANUAL;
    greenLED.ledSetMode(SMARTLED_BLINK,1000,1000); //led in manual mode
    // read the analog in value:
    sensorValue = analogRead(A0);            
    //outputValue = map(sensorValue, 0, 1023, MIN_SERVO_POS,MAX_SERVO_POS);
    state.temperature = map(sensorValue, 1023, 0, MIN_BOILER_TEMP,MAX_BOILER_TEMP);
    state.temperature = round((float)state.temperature/5)*5;
    
    outputValue = map(state.temperature, MIN_BOILER_TEMP, MAX_BOILER_TEMP,MAX_SERVO_POS, MIN_SERVO_POS);
    
    controlServo.write(outputValue);
    
    //if (DEBUG)  Serial.print("sensor = " );                       
    //if (DEBUG)  Serial.print(sensorValue);      
    //if (DEBUG)  Serial.print("\t servo = ");      
    //if (DEBUG)  Serial.println(outputValue);  
    
    //if ((millis()/1000)%1 != 0)
    getWebRequest();//process only onese a second

    //delay(50);
    break;       

  case AUTO:
  
    state.mode=AUTO;
    greenLED.ledSetMode(SMARTLED_ON,1000,1000);
    rc = getWebRequest();
    if (rc == UPDATE_PARM){
      Serial.println("+++++++++++++ CHANGE  OF STATE BY WEB REQUEST ++++++++++++++++++++++++++");
        
      if (state.homeAway){
        outputValue = map(state.temperature, MIN_BOILER_TEMP, MAX_BOILER_TEMP,MAX_SERVO_POS, MIN_SERVO_POS);
        //outputValue = (MIN_SERVO_POS+MAX_SERVO_POS)-outputValue;
        controlServo.write(outputValue);
      }else 
        controlServo.write(MAX_SERVO_POS);
    }
    break;
  }

}











